package com.manage.platform.utils;

import com.manage.platform.constants.JwtConstant;
import com.manage.platform.exception.CommonException;
import com.manage.platform.exception.EmError;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * JWT工具类
 */
@Component
public class JwtTokenUtil {

    // token前缀
    public static String tokenPrefix = JwtConstant.TOKEN_PREFIX;

    // 签名密钥
    public static String secret = JwtConstant.JWT_SECRET_KEY;

    // 默认有效期
    public static Long expireTime = JwtConstant.EXPIRATION_REMEMBER * 1000L;

    /**
     * 创建JWT Token
     * @param sub token主体
     * @return 创建的Token字符串
     */
    public static String createToken(String sub) {
        return tokenPrefix + Jwts.builder()
                .setSubject(sub)
                .setExpiration(new Date(System.currentTimeMillis() + expireTime))
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }

    /**
     * 创建JWT Token
     * @param sub token主体
     * @param time 过期时间
     * @return 创建的Token字符串
     */
    public static String createToken(String sub, Long time) {
        return tokenPrefix + Jwts.builder()
                .setSubject(sub)
                .setExpiration(new Date(System.currentTimeMillis() + time))
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }

    /**
     * 验证Token是否正确
     * @param token 需要验证的Token字符串
     * @return 如果Token验证成功，返回token中包含的subject字符串；否则抛出异常
     */
    public static String validateToken(String token) {
        try {
            Claims claims = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token.replace(tokenPrefix, ""))
                    .getBody();
            return claims.getSubject();
        } catch (ExpiredJwtException e) {
            throw new CommonException(EmError.AUTH_TOKEN_EXPIRED);
        } catch (Exception e) {
            throw new CommonException(EmError.AUTH_TOKEN_INVALID);
        }
    }

    /**
     * 检查Token是否需要更新
     * @param token 需要验证的Token字符串
     * @return 如果Token需要更新，则返回true；否则返回false
     */
    public static boolean isNeedUpdate(String token) {
        try {
            Claims claims = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token.replace(tokenPrefix, ""))
                    .getBody();
            // 如果剩余过期时间少于过期时常的一半，则需要更新Token
            return (claims.getExpiration().getTime() - System.currentTimeMillis()) < (expireTime >> 1);
        } catch (ExpiredJwtException e) {
            // 如果token过期，则需要更新Token
            return true;
        } catch (Exception e) {
            throw new CommonException(EmError.AUTH_TOKEN_INVALID);
        }
    }
}
